package com.songcha.library_base.mvvm.base

import android.app.Application
import androidx.lifecycle.MutableLiveData
import com.songcha.library_base.interfaces.IApiResult
import com.songcha.library_base.interfaces.ILoadMoreData
import com.songcha.library_base.interfaces.IRefreshData
import com.songcha.library_base.interfaces.IResult
import com.songcha.library_base.mvvm.exception.CodeException
import com.songcha.library_base.mvvm.exception.LoginTokenInvalidException
import com.songcha.library_base.mvvm.exception.NoDataException
import com.songcha.library_base.mvvm.exception.NoNetworkException
import com.songcha.library_common.util.ToastUtil
import com.songcha.library_network.bean.BaseBean


import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.net.ConnectException
import java.net.SocketTimeoutException


abstract class BaseRefreshLoadMoreViewModel<R:BaseRepository,RLST>(app: Application) : BaseRefreshViewModel<R,RLST>(app),
    IRefreshData, ILoadMoreData {
    val rlmlst = MutableLiveData<MutableList<Any>>()

    enum class LoadMoreState{
        LOADINGMORE,
        LOADMORE_SUCCESS,
        LOADMORE_ERROR,
        LOADMORE_TIMEOUT,
        LOADMORE_NO_DATA,
        LOADMORE_NO_NETWORK,
        LOADMORE_CONNECT_ERROR,
    }

    var isLoadingMore = false
    var loadMore_error:Throwable? = null
    val loadMore_state : MutableLiveData<LoadMoreState> = MutableLiveData<LoadMoreState>()
    var loadMoreStart = 0
    var loadMoreCount = 0
    var currentPage = 1
    var lastPage = 1


    override fun onSetStateStateSubscribe() {
        if(isRefreshing){
            onRefreshing()
        }else if(isLoadingMore){
            onLoadingMore()
        }else{
            onLoading()
        }
    }

    override fun onSetStateNoNetwork() {
        if(isRefreshing){
            onRefreshNoNetwork()
        }else if(isLoadingMore){
            onLoadMoreNoNetwork()
        }else{
            onLoadNoNetwork()
        }
    }

    override fun onSetStateConnectError() {
        if(isRefreshing){
            onRefreshConnectError()
        }else if(isLoadingMore){
            onLoadMoreConnectError()
        }else{
            onLoadConnectError()
        }
    }

    override fun onSetStateNoData() {
        if(isRefreshing){
            onRefreshNoData()
        }else if(isLoadingMore){
            onLoadMoreNoData()
        }else{
            onLoadNoData()
        }
    }

    override fun onSetStateTimeout() {
        if(isRefreshing){
            onRefreshTimeOut()
        }else if(isLoadingMore){
            onLoadMoreTimeout()
        }else{
            onLoadTimeOut()
        }
    }

    override fun onSetStateError(e: Throwable) {
        if(isRefreshing){
            onRefreshError(e)
        }else if(isLoadingMore){
            onLoadMoreError(e)
        }else{
            onLoadError(e)
        }
    }


    override fun onRefreshSuccess() {
        super.onRefreshSuccess()
    }

    override fun onRefreshing() {
        super.onRefreshing()
        //save currentpage and restore when refresh error
        lastPage = currentPage
        currentPage = 1
    }

    override fun onRefreshError(e: Throwable) {
        super.onRefreshError(e)
        currentPage = lastPage
    }

    override fun onRefreshNoData() {
        super.onRefreshNoData()
        currentPage = lastPage
    }

    override fun onRefreshNoNetwork() {
        super.onRefreshNoNetwork()
        currentPage = lastPage
    }

    override fun onRefreshConnectError() {
        super.onRefreshConnectError()
        currentPage = lastPage
    }


    override fun onRefreshTimeOut() {
        super.onRefreshTimeOut()
        currentPage = lastPage
    }


    override fun onLoadingMore() {
        isLoadingMore = true
        currentPage++
        loadMore_state.value = LoadMoreState.LOADINGMORE
    }

    override fun onLoadMoreSuccess(start: Int, count: Int) {
        isLoadingMore = false
        loadMoreStart = start
        loadMoreCount = count
        loadMore_state.value = LoadMoreState.LOADMORE_SUCCESS
    }

    override fun onLoadMoreError(e:Throwable) {
        loadMore_error = e
        isLoadingMore = false
        currentPage--
        loadMore_state.value = LoadMoreState.LOADMORE_ERROR
    }

    override fun onLoadMoreTimeout() {
        isLoadingMore = false
        currentPage--
        loadMore_state.value = LoadMoreState.LOADMORE_TIMEOUT
    }

    override fun onLoadMoreNoData() {
        isLoadingMore = false
        currentPage--
        loadMore_state.value = LoadMoreState.LOADMORE_NO_DATA
    }

    override fun onLoadMoreNoNetwork() {
        isLoadingMore = false
        currentPage--
        loadMore_state.value = LoadMoreState.LOADMORE_NO_NETWORK
    }

    override fun onLoadMoreConnectError() {
        isLoadingMore=false
        currentPage--
        loadMore_state.value = LoadMoreState.LOADMORE_CONNECT_ERROR
    }

    /***
     * handle load,refresh,loadmore state when getdata success
     */
    override fun handleDataListSuccess(newList:MutableList<RLST>){
        if(isRefreshing){
            if(newList.size == 0){
                onRefreshNoData()
            }else{
                rlst.value = newList
                rlmlst.value = newList as MutableList<Any>
                onRefreshSuccess()
            }
        }else if(isLoadingMore){
            if(newList.size == 0){
                onLoadMoreNoData()
            }else{
                var start = 0
                var size = newList.size
                if(rlst.value == null || rlst.value!!.size == 0){
                    rlst.value = newList
                    rlmlst.value = newList as MutableList<Any>
                }else{
                    //recyclerview must be shallow copy
                    val tmp = rlst.value!!
                    start = tmp!!.size
                    size = newList.size
                    tmp.addAll(newList)
                    rlst.value = tmp

                    //val tmp2 = rlst.value!!
                    //tmp2.addAll(newRlmst as MutableList<RLST>)
                    rlmlst.value = rlst.value!! as MutableList<Any>

                }
                onLoadMoreSuccess(start,size)
            }

        }else{
            if(newList.size == 0){
                onLoadNoData()
            }else{
                rlst.value = newList
                rlmlst.value = newList as MutableList<Any>
                onLoadSuccess()
            }
        }

    }



}